/*
 *  ColourFader.cpp
 *
 *  Created by Pat Long (plong0) on 19/05/09.
 *  Copyright 2009 Tangible Interaction Inc. All rights reserved.
 *
 */

#include "ColourFader.h"

ColourFader::ColourFader(){
	this->init();
}

ColourFader::~ColourFader(){
	for(vector<ColourFader::FaderColourRGBA*>::iterator it = this->transitions.begin(); it != this->transitions.end(); it++){
		delete (*it);
	}
}

void ColourFader::init(){
	this->defaultColour.setRGBA(255, 255, 255, 255);
	this->currentColour.setRGBA(255, 255, 255, 255);
	this->currFader = -1;
}

int ColourFader::nextTransition(){
	if(++this->currFader >= this->transitions.size())
		this->currFader = 0;
	this->transitions[this->currFader]->reset();
	return this->currFader;
}

ColourFader::FaderColourRGBA* ColourFader::addTransition(ColourRGBA* colour1, ColourRGBA* colour2, int transitionFrames){
	FaderColourRGBA* newFader = new ColourFader::FaderColourRGBA(colour1, colour2, transitionFrames);
	this->transitions.push_back(newFader);
	if(this->currFader == -1)
		this->currFader = 0;
	return newFader;
}

void ColourFader::setDefaultColour(float r, float g, float b, float a){
	this->defaultColour.setRGBA(r, g, b, a);
	if(this->currFader == -1)
		this->currentColour.setRGBA(r, g, b, a);
}

void ColourFader::setDefaultColour(ColourRGBA* colour){
	this->setDefaultColour(colour->r, colour->g, colour->b, colour->a);
}

ColourRGBA* ColourFader::getCurrentColour(){
	if(this->currFader >= 0 && this->transitions.size() > 0 && this->currFader < this->transitions.size()){
		this->transitions[this->currFader]->getCurrentColour(&this->currentColour);
	}
	else{
		this->currentColour.r = this->defaultColour.r;
		this->currentColour.g = this->defaultColour.g;
		this->currentColour.b = this->defaultColour.b;
		this->currentColour.a = this->defaultColour.a;
	}
	return &this->currentColour;
}

ColourRGBA* ColourFader::getNextColour(){
	ColourRGBA* res = this->getCurrentColour();
	if(this->currFader >= 0 && this->transitions.size() > 0 && this->currFader < this->transitions.size()){
		float check = this->transitions[this->currFader]->nextFrame() * 100.0;
		if(check >= 100.0){
			this->nextTransition();
		}
	}
	return res;
}

ColourRGBA* ColourFader::getColourAtPercent(float percent){
	// TODO: need to implement this... tricky with the different transitions
	return this->getCurrentColour();
}

ColourRGBA* ColourFader::activateCurrent(){
	ofSetColor(this->currentColour.r, this->currentColour.g, this->currentColour.b, this->currentColour.a);
	return &this->currentColour;
}

ColourRGBA* ColourFader::activateCurrentAndAdvance(){
	ColourRGBA* colour = this->getNextColour();
	ofSetColor(this->currentColour.r, this->currentColour.g, this->currentColour.b, this->currentColour.a);
	return colour;
}


ColourFader::FaderColourRGBA::FaderColourRGBA(ColourRGBA* colour1, ColourRGBA* colour2, int transitionFrames){
	this->init(colour1, colour2, transitionFrames);
}

ColourFader::FaderColourRGBA::~FaderColourRGBA(){
	delete this->colour1;
	delete this->colour2;
}

void ColourFader::FaderColourRGBA::init(ColourRGBA* colour1, ColourRGBA* colour2, int transitionFrames){
	this->colour1 = colour1;
	this->colour2 = colour2;
	this->increments = NULL;
	this->totalFrames = transitionFrames;
	this->currFrame = 0;
	this->calculateIncrements();
}

void ColourFader::FaderColourRGBA::calculateIncrements(){
	if(this->colour1 != NULL && this->colour2 != NULL){
		if(this->increments == NULL)
			this->increments = new ColourRGBA();
		if(this->totalFrames > 1){
			this->increments->r = (float)(this->colour2->r - this->colour1->r) / (float)(this->totalFrames-1);
			this->increments->g = (float)(this->colour2->g - this->colour1->g) / (float)(this->totalFrames-1);
			this->increments->b = (float)(this->colour2->b - this->colour1->b) / (float)(this->totalFrames-1);
			this->increments->a = (float)(this->colour2->a - this->colour1->a) / (float)(this->totalFrames-1);
		}
		else{
			this->increments->r = (float)(this->colour2->r - this->colour1->r);
			this->increments->g = (float)(this->colour2->g - this->colour1->g);
			this->increments->b = (float)(this->colour2->b - this->colour1->b);
			this->increments->a = (float)(this->colour2->a - this->colour1->a);
		}
	}
}

float ColourFader::FaderColourRGBA::getPercent(){
	if(this->totalFrames > 0)
		return (float)this->currFrame/(float)this->totalFrames;
	else
		return 100.0;
}

ColourRGBA* ColourFader::FaderColourRGBA::getCurrentColour(ColourRGBA* colour){
	if(colour != NULL){
		if(this->currFrame == this->totalFrames)
			this->currFrame--;
		if(this->currFrame < this->totalFrames){
			colour->r = (float)this->colour1->r + (float)this->increments->r * (float)this->currFrame;
			colour->g = (float)this->colour1->g + (float)this->increments->g * (float)this->currFrame;
			colour->b = (float)this->colour1->b + (float)this->increments->b * (float)this->currFrame;
			colour->a = (float)this->colour1->a + (float)this->increments->a * (float)this->currFrame;
		}
	}
	return colour;
}

float ColourFader::FaderColourRGBA::nextFrame(){
	if(++this->currFrame > this->totalFrames)
		this->currFrame = this->totalFrames;
	return this->getPercent();
}

void ColourFader::FaderColourRGBA::reset(){
	this->currFrame = 0;
}
